--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
scripts/ci/check_schema_migrations.py 6d6b40536aa49435a195fce36c4c3e4b8d96c738 (6d6b4053) Text, 3.02 KB
T8b949e#!/usr/bin/env python3
T8b949e# SPDX-License-Identifier: 0BSD
T8b949e"""Fail when schema migrations contain destructive SQL without an explicit allow tag."""
Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations
Tff7b72import T7ee787re
Tff7b72import T7ee787sys
Tff7b72from T7ee787pathlib Tff7b72import Te6edf3Path
Te6edf3ROOT Tff7b72= Te6edf3PathTb4b4b4(Tff7b72__file__Tb4b4b4)Tff7b72.Td2a8ffresolveTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffparentsTb4b4b4[T79c0ff2Tb4b4b4]
Te6edf3SCHEMA Tff7b72= Te6edf3ROOT Tff7b72/ Ta5d6ff"Ta5d6ffmeshchatx/src/backend/database/schema.pyTa5d6ff"
Te6edf3FIXTURE_MANIFEST Tff7b72= Te6edf3ROOT Tff7b72/ Ta5d6ff"Ta5d6fftests/backend/fixtures/schema_versions/manifest.jsonTa5d6ff"
Te6edf3DESTRUCTIVE Tff7b72= Te6edf3reTff7b72.Td2a8ffcompileTb4b4b4(
Ta5d6ffrTa5d6ff"Ta5d6ff(DROPTa5d6ff\Ta5d6ffs+TABLE|DROPTa5d6ff\Ta5d6ffs+COLUMN|ALTERTa5d6ff\Ta5d6ffs+TABLETa5d6ff\Ta5d6ffs+.+Ta5d6ff\Ta5d6ffs+RENAME)Ta5d6ff"Tb4b4b4,
Te6edf3reTff7b72.Td2a8ffIGNORECASETb4b4b4,
Tb4b4b4)
Te6edf3DELETE_FROM Tff7b72= Te6edf3reTff7b72.Td2a8ffcompileTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ffDELETETa5d6ff\Ta5d6ffs+FROMTa5d6ff"Tb4b4b4, Te6edf3reTff7b72.Td2a8ffIGNORECASETb4b4b4)
Te6edf3DEDUP_DELETE Tff7b72= Te6edf3reTff7b72.Td2a8ffcompileTb4b4b4(Ta5d6ffrTa5d6ff"Ta5d6ffNOTTa5d6ff\Ta5d6ffs+INTa5d6ff\Ta5d6ffs*Ta5d6ff\Ta5d6ff(Ta5d6ff\Ta5d6ffs*SELECTTa5d6ff"Tb4b4b4, Te6edf3reTff7b72.Td2a8ffIGNORECASETb4b4b4)
Te6edf3ALLOW_TAG Tff7b72= Ta5d6ff"Ta5d6ffmigration-safety: allow-destructiveTa5d6ff"
Tff7b72def Td2a8ff_run_migrations_sourceTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
Te6edf3text Tff7b72= Te6edf3SCHEMATff7b72.Td2a8ffread_textTb4b4b4(Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)
Te6edf3marker Tff7b72= Ta5d6ff"Ta5d6ffdef _run_migrationsTa5d6ff"
Te6edf3start Tff7b72= Te6edf3textTff7b72.Td2a8ffindexTb4b4b4(Te6edf3markerTb4b4b4)
Te6edf3rest Tff7b72= Te6edf3textTb4b4b4[Te6edf3startTb4b4b4:Tb4b4b4]
Te6edf3depth Tff7b72= T79c0ff0
Te6edf3end Tff7b72= Tffa657lenTb4b4b4(Te6edf3restTb4b4b4)
Tff7b72for Te6edf3iTb4b4b4, Te6edf3ch Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3restTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3ch Tff7b72== Ta5d6ff"Tffea00\nTa5d6ff" Tff7b72and Te6edf3restTb4b4b4[Te6edf3i Tb4b4b4: Te6edf3i Tff7b72+ T79c0ff4Tb4b4b4] Tff7b72== Ta5d6ff"Tffea00\nTa5d6ff def Ta5d6ff" Tff7b72and Te6edf3depth Tff7b72== T79c0ff0 Tff7b72and Te6edf3i Tff7b72> T79c0ff20Tb4b4b4:
Te6edf3end Tff7b72= Te6edf3i
Tff7b72break
Tff7b72return Te6edf3restTb4b4b4[Tb4b4b4:Te6edf3endTb4b4b4]
Tff7b72def Td2a8ff_check_schema_fixturesTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657strTb4b4b4]Tb4b4b4:
Te6edf3errorsTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Tff7b72not Te6edf3FIXTURE_MANIFESTTff7b72.Td2a8ffis_fileTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(
Ta5d6ff"Ta5d6ffschema fixture manifest missing; run task schema-fixturesTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3errors
Tff7b72import T7ee787json
Te6edf3sysTff7b72.Td2a8ffpathTff7b72.Td2a8ffinsertTb4b4b4(T79c0ff0Tb4b4b4, Tffa657strTb4b4b4(Te6edf3ROOTTb4b4b4)Tb4b4b4)
Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787databaseT7ee787.T7ee787schema Tff7b72import Te6edf3DatabaseSchema
Te6edf3latest Tff7b72= Te6edf3DatabaseSchemaTff7b72.Td2a8ffLATEST_VERSION
Te6edf3data Tff7b72= Te6edf3jsonTff7b72.Td2a8ffloadsTb4b4b4(Te6edf3FIXTURE_MANIFESTTff7b72.Td2a8ffread_textTb4b4b4(Te6edf3encodingTff7b72=Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Tffa657intTb4b4b4(Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflatest_versionTa5d6ff"Tb4b4b4, Tff7b72-T79c0ff1Tb4b4b4)Tb4b4b4) Tff7b72!= Te6edf3latestTb4b4b4:
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffschema fixtures stale (manifest latest Tffd700{Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff'Ta5d6fflatest_versionTa5d6ff'Tb4b4b4)Tffd700}Ta5d6ff, Ta5d6ff"
Ta5d6fffTa5d6ff"Ta5d6ffcode Tffd700{Te6edf3latestTffd700}Ta5d6ff); run task schema-fixturesTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3errors
Tff7b72def Td2a8ffmainTb4b4b4(Tb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
Tff7b72if Tff7b72not Te6edf3SCHEMATff7b72.Td2a8ffis_fileTb4b4b4(Tb4b4b4)Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffcheck_schema_migrations: missing Tffd700{Te6edf3SCHEMATffd700}Ta5d6ff"Tb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Tff7b72return T79c0ff1
Te6edf3violationsTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3line Tff7b72in Te6edf3_run_migrations_sourceTb4b4b4(Tb4b4b4)Tff7b72.Td2a8ffsplitlinesTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3stripped Tff7b72= Te6edf3lineTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3stripped Tff7b72or Te6edf3strippedTff7b72.Td2a8ffstartswithTb4b4b4(Ta5d6ff"Ta5d6ff#Ta5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3ALLOW_TAG Tff7b72in Te6edf3lineTb4b4b4:
Tff7b72continue
Tff7b72if Te6edf3DESTRUCTIVETff7b72.Td2a8ffsearchTb4b4b4(Te6edf3lineTb4b4b4)Tb4b4b4:
Te6edf3violationsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3strippedTb4b4b4)
Tff7b72continue
Tff7b72if Te6edf3DELETE_FROMTff7b72.Td2a8ffsearchTb4b4b4(Te6edf3lineTb4b4b4) Tff7b72and Tff7b72not Te6edf3DEDUP_DELETETff7b72.Td2a8ffsearchTb4b4b4(Te6edf3lineTb4b4b4)Tb4b4b4:
Te6edf3violationsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3strippedTb4b4b4)
Tff7b72if Te6edf3violationsTb4b4b4:
Tffa657printTb4b4b4(
Ta5d6ff"Ta5d6ffcheck_schema_migrations: destructive SQL in _run_migrations Ta5d6ff"
Ta5d6fffTa5d6ff"Ta5d6ff(prefer expand-only migrations or add Tffd700{Te6edf3ALLOW_TAGTffd700}Ta5d6ff on the line):Ta5d6ff"Tb4b4b4,
Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3v Tff7b72in Te6edf3violationsTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Tffd700{Te6edf3vTffd700}Ta5d6ff"Tb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Tff7b72return T79c0ff1
Te6edf3fixture_errors Tff7b72= Te6edf3_check_schema_fixturesTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3fixture_errorsTb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffcheck_schema_migrations:Ta5d6ff"Tb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Tff7b72for Te6edf3err Tff7b72in Te6edf3fixture_errorsTb4b4b4:
Tffa657printTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ff Tffd700{Te6edf3errTffd700}Ta5d6ff"Tb4b4b4, Te6edf3fileTff7b72=Te6edf3sysTff7b72.Td2a8ffstderrTb4b4b4)
Tff7b72return T79c0ff1
Tff7b72return T79c0ff0
Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Tff7b72raise Tf85149SystemExitTb4b4b4(Te6edf3mainTb4b4b4(Tb4b4b4)Tb4b4b4)
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────